
	
	public function init( source, target )
	{
		variables.source = source;
		variables.target = target;
		
		variables.queuedPropertyResolvers = [];
		variables.queuedAggregates = [];
		variables.resolverProperties = {};
		variables.unresolvedPropertiesByName = {};
		variables.unresolvedPropertiesByType = {};
		variables.aggregatedTargetProperties = {};
		variables.ignoredProperties = [];
		
		return this;
	}
	
	private function dequeueDelayedConfiguration()
	{
		addQueuedPropertyResolvers();
		addQueuedAggregates();
	}
	
	private function addQueuedPropertyResolvers()
	{
		var resolver = "";
		
		while ( arrayLen( queuedPropertyResolvers ) > 0 )
		{
			resolver = queuedPropertyResolvers.pop();
			addPropertyResolver.apply( this, [ resolver ] )
		}
	}
	
	private function addQueuedAggregates()
	{
		var args = "";
		
		while ( arrayLen( queuedAggregates ) > 0 )
		{
			args = queuedAggregates.pop();
			setAggregatedType.apply( this, args );
		}
	}
	
	/**
	 * Adds mapping-based resolutions that have been registered with the assigned
	 * mapper _after_ this one.
	 */
	private function createLateMappedPropertyResolutions()
	{
		var unresolvedProperty = "";
		
		if ( isNull( mapper ) )
		{
			throw new Error( "Can't resolve late mapped properties without a mapper!" );
		}
		
		for each ( unresolvedProperty in unresolvedPropertiesByType )
		{
			if ( mapper.mappingExistsBetween( unresolvedProperty.getSourceProperty().getMetadata(), unresolvedProperty.getTargetProperty().getMetadata() ) )
			{
				var resolver = new PropertyResolver();
				resolver.sourceProperty = unresolvedProperty.getSourceProperty().getName();	
				resolver.targetProperty = unresolvedProperty.getTargetProperty().getName(); 	
				resolver.valueResolutionFunction = createObject( "component", "com.firemoss.atonement.mapper.resolution.MappedValueResolver" ).resolve;
				
				addPropertyResolver( resolver );
			}
		}
	}
	
	internal function resolveProperties( resolverFactory )
	{
		var sourceProperties = metadataBuilder.buildMetadataForClass( source ).propertyMetadata	
		var targetProperties = metadataBuilder.buildMetadataForClass( target ).propertyMetadata	
		var targetProperty = "";
		var sourceProperty = ""
		for each ( var targetProperty : Property in targetProperties )
		{
			// Don't overwrite explicitly resolved properties!
			if ( resolvedProperties[ targetProperty.name ] == null || !PropertyResolution( resolvedProperties[ targetProperty.name ] ).explicit )
			{
				
				if ( sourceProperties.containsProperty( targetProperty.name ) )
				{
					var sourceProperty : Property = sourceProperties.getProperty( targetProperty.name )
					
					if ( sourceProperty.type == targetProperty.type )
					{
						var resolver : PropertyResolution = new PropertyResolution()
							
						/*
						resolver.sourceProperty = sourceProperties.getProperty( targetProperty.name )
						resolver.targetProperty = targetProperties.getProperty( targetProperty.name )
					*/
						resolver.sourceProperty = sourceProperty
						resolver.targetProperty = targetProperty
						resolver.valueResolutionFunction = resolverFactory.create( sourceProperty.type ).resolve
							
						resolvedProperties[ targetProperty.name ] = resolver
					}
					else
					{
						var unresolvedByType : UnresolvedTypeMapping = new UnresolvedTypeMapping()
						unresolvedByType.source = source
						unresolvedByType.target = target
						unresolvedByType.sourceProperty = sourceProperty
						unresolvedByType.targetProperty = targetProperty
						unresolvedPropertiesByType[ targetProperty.name ] = unresolvedByType
					}
					
					// Is the target type an IList or Dictionary?  State that we need resolution of what to create when walking
					// the graph.
					try
					{
						var instance : * = new targetProperty.type.clazz()
						
						if ( instance is IList || instance is Dictionary )
						{
							aggregatedTargetProperties[ targetProperty.name ] = targetProperty
						}
					}
					catch ( e : Error )
					{
						// Well, that obviously wasn't something representing a collection, was it?
					}
				}
				else
				{
					var unresolvedByName : UnresolvedNameMapping = new UnresolvedNameMapping()
					unresolvedByName.source = source
					unresolvedByName.target = target
					unresolvedByName.targetProperty = targetProperty
					unresolvedPropertiesByName[ targetProperty.name ] = unresolvedByName
				}
				
				// Post-processed metadata
				if ( honorAnnotations )
				{
					if ( targetProperty.ignored )
					{
						ignoreProperty( targetProperty.name )
					}
					
					if ( targetProperty.collectionOf )
					{
						setAggregatedType( targetProperty.name, targetProperty.collectionOf )
					}
					
					if ( targetProperty.valueResolutionFunction != null )
					{
						var annotatedResolver : PropertyResolver = new PropertyResolver()
						annotatedResolver.targetProperty = targetProperty.name
						annotatedResolver.sourceProperty = targetProperty.sourcePropertyName
						annotatedResolver.valueResolutionFunction = targetProperty.valueResolutionFunction
						this.addPropertyResolver( annotatedResolver )
					}
				}
			}
		}
		
		dequeueDelayedConfiguration()
	}
	
